<?php
/**
 * 系统自动加载GI基类库和当前项目的model和Action对象
 * @param string $classname 对象类名
 * @return void
 */
function __autoload($classname)
{
	static $_cache = array();
	if(empty($_cache)){
	 	$_cache = include(PATH_GI_COMMON . 'Alias.php');
	 	if(file_exists(PATH_APP_COMMON . 'Alias.php')){
	 		$appAlias = include(PATH_APP_COMMON . 'Alias.php');
	 		$_cache = array_merge($_cache,$appAlias);
	 	}
	}
	
	if(in_array($classname,array_keys($_cache))){
		include_once($_cache[$classname]);
	} else {
		$path = str_replace('_','/',$classname);
		include_once($path . ".php");
	}
		
}
//获取配置值
function C($name='',$value=null) {
    static $_config = array();

    is_string($name) && $name = strtolower($name);

    
    if(!is_null($value)) {// 参数赋值
		$_config[$name] = $value;
        return;
    }
    
    if(empty($name)) {	// 获取全部配置参数
        return $_config;
    } elseif(is_array($name)) { // 批量赋值
        $_config = array_merge($_config,array_change_key_case($name));
        return $_config;
    }elseif(isset($_config[strtolower($name)])) { // 获取参数
        return $_config[strtolower($name)];
    }else{
        return null;
    }
}


// 取得Model实例
function M($modelName,$method='',$args=array()){
	$className = "Model_$modelName";
	if(!class_exists($className)){
		if(!class_exists($className)){
			$script = '
			class Model_' . $modelName .' extends Model {
				protected $modelName = "' . $modelName .'";
			}';
		}
		eval($script);
	}
		
	return _getSingleton($className, $method, $args);
}

// 取得对象实例 支持调用类的静态方法
function _getSingleton($className,$method='',$args=array())
{
    static $_instance = array();
    if(empty($args)) {
        $identify   =   $className.$method;
    }else{
        $identify   =   $className.$method.to_guid_string($args);
    }
    if (!isset($_instance[$identify])) {
        if(class_exists($className)){
            $o = new $className();
            if(method_exists($o,$method)){
                if(!empty($args)) {
                    $_instance[$identify] = call_user_func_array(array(&$o, $method), $args);
                }else {
                    $_instance[$identify] = $o->$method();
                }
            }
            else
                $_instance[$identify] = $o;
        }
        else
            _halt(MESSAGE_CLASS_NOT_EXIST.$className);
    }
    return $_instance[$identify];
}
/**
 * 提示消息
 * @param string $msg
 */
function _message($msg){
	echo '<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>';
	echo "<body>$msg</body>";
	die();
}

// 自定义异常处理 错误输出
function _halt($error) {
    if(IS_CLI) {
        exit ($error);
    }
    $e = array();
    if(C('DEBUG_MODE')){
    	if(is_object($error)){
    		$objType = get_class($error);
    		if (substr($objType,-9) == "Exception") {
    			$e = $error->__toString();
    		}
    	} else {
            $trace = debug_backtrace();
            array_shift($trace);
            $e['message'] = $error;
            $e['file'] = $trace[0]['file'];
            $e['class'] = $trace[0]['class'];
            $e['function'] = $trace[0]['function'];
            $e['line'] = $trace[0]['line'];
            $traceInfo='';
            $time = date("y-m-d H:i:m");
            foreach($trace as $t)
            {
                $traceInfo .= '['.$time.'] '.$t['file'].' ('.$t['line'].') ';
                $traceInfo .= $t['class'].$t['type'].$t['function'].'(';
                $traceInfo .= implode(', ', $t['args']);
                $traceInfo .=")<br/>";
            }
            $e['trace']  = $traceInfo;
        }
        
        // 使用默认的异常模板文件
        include PATH_GI_TPL.'Exception.tpl.php';
        echo "<pre>";
        print_r(_trace());
        echo "</pre>";
    }
    else
    {
        //否则定向到错误页面
      	die("Error");
    }
    exit;
}
/**
 * 根据PHP各种类型变量生成唯一标识号
 * @param mix $mix
 * @return string
 */
function _toUniqueId($mix){
    if(is_object($mix) && function_exists('spl_object_hash')) {
        return spl_object_hash($mix);
    }elseif(is_resource($mix)){
        $mix = get_resource_type($mix).strval($mix);
    }else{
        $mix = serialize($mix);
    }
    return md5($mix);
}
/**
 * Do trim function on all the children of one multidimensional array
 *  
 * @param array $obj
 * 
 * @return array
 * 
 **/
function _trimAll($obj){
	if(is_array($obj)){
		foreach($obj as $key=>$val)
			$obj[$key] = _trimAll($val);
	} else {
		$obj =  trim($obj);
	}
	return $obj;
}

/**
 * Do addslashes function on all the children of one multidimensional array
 * @param array $array
 * @return array
 * 
 **/
function _addSlashes($array){
	if(is_array($array)){
		foreach($array as $key=>$val)
			$array[$key] = _addSlashes($val);
	} else {
		$array =  addslashes($array);
	}
	return $array;
}
/**
 * Do stripslashes function on all the children of one multidimensional array
 * @param array $array
 * @return array
 * 
 **/
function _stripSlashes($array){
	if(is_array($array)){
		foreach($array as $key=>$val)
			$array[$key] = _stripSlashes($val);
	} else {
		$array =  stripcslashes($array);
	}
	return $array;
}

function _include_once($file_name){
	$file_name = str_replace("_","/",$file_name.".php");
	include_once($file_name);
}

//Get the TPL engine
function _getView($dir=""){
	
	static $smarty = null;
	
	if($smarty == null) {
		$smarty = new Helper_Tpl();
	}
	
	$smarty->left_delimiter = '<?';
	$smarty->right_delimiter = '?>';
	$smarty->view_dir = PATH_APP_VIEW;
	$smarty->template_dir = $dir;
	$smarty->compile_dir = 'templates_c/';
	return $smarty;
}

/**
 * Generate the url according to giving parameters
 * 
 * @param string $ctl     Controller's name
 * @param string $action     Controller's action
 * @param string $parameter    attached other parameter(eg name=john&age=10)
 * 
 * @return string
 * */
function _url($ctl,$action='',$parameter=''){
	$ret = "";
	if($ctl != ''){
		$ret .= URL_WEB . "?" . C('VAR_CONTROLLER') . "=" . $ctl;
		if($action  != ''){
			$ret .= "&" . C('VAR_ACTION') . "=" . $action;
		}
		if($parameter != ""){
			$ret .= "&" . $parameter;
		}
	}
	return $ret;	
}

/**
 * obtain  GET  parameter
 * 
 * @param string $varname
 * @param string $type
 *               $type should be in {int,string}
 * 
 * @return mix
 * */
function _get($varname, $type){
	$ret = "";
	if(isset($_GET[$varname])){
		if (!is_array($_GET[$varname])) {
			$_GET[$varname] = trim($_GET[$varname]);
		}
		switch ($type){
			case 'int':
			case 'intval':
				$ret = intval($_GET[$varname]);
				break;
			case 'str':
			case 'string':
				$ret = addslashes($_GET[$varname]);
				break;
			case 'arr':
			case 'array':
				$ret = $_GET[$varname];
				foreach($ret as &$var){
					$var = _addSlashes($var);
				}
		}
	}
	return $ret;
}
/**
 * 
 * obtain  POST  parameter 
 * 
 * @param string $varname
 * @param string $type
 *               $type should be in {int,string}
 * 
 * @return mix
 * */
function _post($varname,$type){
	$ret = "";
	if(isset($_POST[$varname])){
		if (!is_array($_POST[$varname])) {
			$_POST[$varname] = trim($_POST[$varname]);
		}
		switch ($type){
			case 'int':
			case 'intval':
				$ret = intval($_POST[$varname]);
				break;
			case 'str':
			case 'string':
				$ret = addslashes($_POST[$varname]);
				break;
			case 'arr':
			case 'array':
				$ret = is_array($_POST[$varname]) ? $_POST[$varname] : array();
				foreach($ret as &$var){
					$var = _addSlashes($var);
				}
		}
	}
	return $ret;
}
/**
 * 
 * obtain  GET or POST  parameter 
 * 
 * @param string $varname
 * @param string $type
 *               $type should be in {int,string}
 * 
 * @return mix
 * */
function _gp($varname,$type){
	$g = _get($varname,$type);
	$p = _post($varname,$type);
	return  ""===$g ? $p : $g;
}

//
function _json2array($json){
	if(is_array($json) || is_object($json)){
		foreach($json as $key=>$val){
				$array[$key] = _json2array($val);
		}
	} else {
		return $json;
	}
	return $array;
}


function _fetchUrl($url,$pars=array()){

	/*
	$pars['POST']
	$pars['COOKIE']
	$pars['AUTH']['USER']
	$pars['AUTH']['PWD']
	*/
	$method = $pars['POST'] ? 'POST' : 'GET';
	
	// Set maximum number of seconds (can have floating-point) to wait for feed before displaying page without feed
	$numberOfSeconds=6;    

   // Suppress error reporting so Web site visitors are unaware if the feed fails
   //error_reporting(0);

   // Extract resource path and domain from URL ready for fsockopen
   $url = str_replace("http://","",$url);
   $urlComponents = explode("/",$url);
   $domain = $urlComponents[0];
   $resourcePath = str_replace($domain,"",$url);

   // Establish a connection
   $socketConnection = @fsockopen($domain, 80, $errno, $errstr, $numberOfSeconds);

   if (!$socketConnection){
	   // You may wish to remove the following debugging line on a live Web site
		$ret = false;
   }    // end if
   else {
	   $ret = '';

		$request = "$method /$resourcePath HTTP/1.0\r\nHost: $domain\r\n";

		if( isset($pars['COOKIE']) ){
			if( is_array($pars['COOKIE']) ) {
				$cookie = array();
				foreach($pars['COOKIE'] as $key => $value){
					$cookie[] = "$key=$value";
				}
				$cookie = implode('&',$cookie);
			}else if( is_string($pars['COOKIE']) ){
				$cookie = $pars['COOKIE'];
			}
		}

		if( isset($cookie) ){
			$request .= "Cookie: " . $cookie . "\r\n";
		}
		if( isset($pars['AUTH']) ){
			$request .="Authorization: Basic " . base64_encode($pars['AUTH']['USER'] . ":" . $pars['AUTH']['PWD']) . "\r\n";
		}
		
		$request .= "Content-Type: application/x-www-form-urlencoded\r\n";

		$postValues = '';
		if( isset($pars['POST']) ){
			
			if( is_array($pars['POST']) ) {
				$postValues = array();
				foreach($pars['POST'] as $key => $value){
					$postValues[] = "$key=$value";
				}
				$postValues = implode('&',$postValues);
			}else if( is_string($pars['POST']) ){
				$postValues = $pars['POST'];
			}

			$length = strlen($postValues);
			$request .= "Content-Length: $length\r\n";
		}

		$request .= "\r\n";
		$request .= $postValues;

		fputs($socketConnection, $request);
		// Loop until end of file
		while (!feof($socketConnection)){
		   $ret .= fgets($socketConnection, 128);
		}// end while
		fclose ($socketConnection);

   }    // end else
   return($ret);
}

/**
 * @return string
 * */
function _getip() {
        if (isset($_SERVER)) {
                if (isset($_SERVER[HTTP_X_FORWARDED_FOR])) {
                        $realip = $_SERVER[HTTP_X_FORWARDED_FOR];
                } elseif (isset($_SERVER[HTTP_CLIENT_IP])) {
                        $realip = $_SERVER[HTTP_CLIENT_IP];
                } else {
                        $realip = $_SERVER[REMOTE_ADDR];
                } 
        } else {
                if (getenv("HTTP_X_FORWARDED_FOR")) {
                        $realip = getenv("HTTP_X_FORWARDED_FOR");
                } elseif (getenv("HTTP_CLIENT_IP")) {
                        $realip = getenv("HTTP_CLIENT_IP");
                } else {
                        $realip = getenv("REMOTE_ADDR");
                } 
        } 
        return $realip;
} 

/**
 * 读取指定缓存的内容，如果缓存内容不存在或失效，则返回 false
 *
 * example:
 * <code>
 * $cacheId = 'my_cache_id';
 * if (!($data = Cache::get($cacheId))) {
 *      $data = 'Data';
 *      Cache::write($data, $cacheId);
 * }
 * </code>
 *
 * 如果 $cacheIdIsFilename 参数为 true，则生成的缓存文件会以 $cacheId 参数作为文件名。
 * 基于安全原因，尽量不要将 $cacheIdIsFilename 参数设置为 true。
 *
 * $time 参数默认为缓存内容的有效期。其计算依据是以缓存文件的最后更新时间为准（也就是最后一次更新该缓存内容的时间）。
 *
 * 如果 $timeIsLifetime 为 false，则 $time 参数表示用于和缓存文件最更新时间进行比较的依据。
 * 如果 $time 指定的时间早于缓存文件的最后更新时间，则判断缓存内容为有效。
 *
 * @param string $cacheId 缓存ID，不同的缓存内容应该使用不同的ID
 * @param int $time 缓存过期时间或缓存生存周期
 * @param boolean $timeIsLifetime 指示 $time 参数的作用
 * @param boolean $cacheIdIsFilename 指示是否用 $cacheId 作为文件名
 *
 * @return mixed 返回缓存的内容，缓存不存在或失效则返回 false
 */
function _getCache($cacheId, $time = 900, $timeIsLifetime = true, $cacheIdIsFilename = false)
{
    $cacheDir = PATH_CACHE;
    $cacheEnable = C('CACHE_ENABLE');
    if ($cacheDir == null || $cacheEnable == false) {
        return false;
    }

    if ($cacheIdIsFilename) {
        $cacheFile = $cacheDir . '/' . $cacheId . '.php';
    } else {
        $cacheFile = $cacheDir . '/' . md5($cacheId) . '.php';
    }
    if (!file_exists($cacheFile)) { return false; }

    if ($timeIsLifetime && $time == -1) {
        return require($cacheFile);
    }

    $filetime = filemtime($cacheFile);
    if ($timeIsLifetime) {
        if (time() >= $filetime + $time) { return false; }
    } else {
        if ($time >= $filetime) { return false; }
    }
    return require($cacheFile);
}

/**
 * 将变量内容写入缓存
 *
 * example:
 * <code>
 * $data = .....; // 要缓存的数据，可以是任何类型的值
 * // cache id 用于唯一指定一个缓存数据，以便稍后取出缓存数据
 * $cacheId = 'data_cahce_1';
 * Cache::write($cacheId, $data);
 * </code>
 *
 * @param string $cacheId
 * @param mixed $data
 * @param boolean $cacheIdIsFilename
 *
 * @return boolean
 */
function _writeCache($cacheId, $data, $cacheIdIsFilename = false)
{
    $cacheDir = PATH_CACHE;
    $cacheEnable = C('CACHE_ENABLE');
    if ($cacheDir == null || $cacheEnable == false) {
        return false;
    }

    if ($cacheIdIsFilename) {
        $cacheFile = $cacheDir . '/' . $cacheId . '.php';
    } else {
        $cacheFile = $cacheDir . '/' . md5($cacheId) . '.php';
    }
    $contents = '<?php return ' . var_export($data, true) . ";\n";
    if (!file_put_contents($cacheFile, $contents)) {
    	die("Cant not write cache file $cacheFile");
        return false;
    } else {
        return true;
    }
}

/**
 * 删除指定的缓存内容
 *
 * @param string $cacheId
 * @param boolean $cacheIdIsFilename
 *
 * @return boolean
 */
function _removeCache($cacheId, $cacheIdIsFilename = false)
{
    $cacheDir = PATH_CACHE;
    $cacheEnable = C('CACHE_ENABLE');
    
    if ($cacheDir == null || $cacheEnable == false) {
        return false;
    }

    if ($cacheIdIsFilename) {
        $cacheFile = $cacheDir . '/' . $cacheId . '.php';
    } else {
        $cacheFile = $cacheDir . '/' . md5($cacheId) . '.php';
    }

    if (file_exists($cacheFile)) {
        return unlink($cacheFile);
    }
    return true;
}
    
function _d($var){
	echo "<pre>";
	print_r($var);
	echo "</pre>";
	die();
}
function D($var){
	return _d($var);
}

function _trace($varvalue = null,$varname = "Noname"){
	static $vars;
	if (func_num_args() == 0) {
		return $vars;
	}
	$vars[$varname][] = $varvalue;

}
if (!function_exists('json_encode'))   
{   
  function json_encode($a=false)   
  {   
    if (is_null($a)) return 'null';   
    if ($a === false) return 'false';   
    if ($a === true) return 'true';   
    if (is_scalar($a))   
    {   
      if (is_float($a))   
      {   
        // Always use "." for floats.   
        return floatval(str_replace(",", ".", strval($a)));   
      }   
  
      if (is_string($a))   
      {   
        static $jsonReplaces = array(array("\\", "/", "\n", "\t", "\r", "\b", "\f", '"'), array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'));   
        return '"' . str_replace($jsonReplaces[0], $jsonReplaces[1], $a) . '"';   
      }   
      else  
        return $a;   
    }   
    $isList = true;   
    for ($i = 0, reset($a); $i < count($a); $i++, next($a))   
    {   
      if (key($a) !== $i)   
      {   
        $isList = false;   
        break;   
      }   
    }   
    $result = array();   
    if ($isList)   
    {   
      foreach ($a as $v) $result[] = json_encode($v);   
      return '[' . join(',', $result) . ']';   
    }   
    else  
    {   
      foreach ($a as $k => $v) $result[] = json_encode($k).':'.json_encode($v);   
      return '{' . join(',', $result) . '}';   
    }   
  }   
}  

/**
 * 加密数据
 * @param mix $data
 * @return string
 */
function _encode($data){
	$str = serialize($data);
	return _authcode($str,'ENCODE');
}

/**
 * 解密数据
 * @param string $string
 * @return mix
 */
function _decode($string){
	$string=str_replace(" ",'+',$string);
	return unserialize(_authcode($string,'DECODE'));
}

/**
 * 来自DZ的加密解密字符串函数
 *
 * @param  string $string 要加密的字符串
 * @param  string $operation  加密 ENCODE, 解密 DECODE
 * @param  string $key 密钥
 * 
 * @return string
 */
function _authcode($string, $operation, $key = '') {

	$key = md5($key ? $key : C('SECRET_KEY'));
	$key_length = strlen($key);

	$string = $operation == 'DECODE' ? base64_decode($string) : substr(md5($string.$key), 0, 8).$string;
	$string_length = strlen($string);

	$rndkey = $box = array();
	$result = '';

	for($i = 0; $i <= 255; $i++) {
		$rndkey[$i] = ord($key[$i % $key_length]);
		$box[$i] = $i;
	}

	for($j = $i = 0; $i < 256; $i++) {
		$j = ($j + $box[$i] + $rndkey[$i]) % 256;
		$tmp = $box[$i];
		$box[$i] = $box[$j];
		$box[$j] = $tmp;
	}

	for($a = $j = $i = 0; $i < $string_length; $i++) {
		$a = ($a + 1) % 256;
		$j = ($j + $box[$a]) % 256;
		$tmp = $box[$a];
		$box[$a] = $box[$j];
		$box[$j] = $tmp;
		$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
	}

	if($operation == 'DECODE') {
		if(substr($result, 0, 8) == substr(md5(substr($result, 8).$key), 0, 8)) {
			return substr($result, 8);
		} else {
			return '';
		}
	} else {
		return str_replace('=', '', base64_encode($result));
	}

}


function _cutstr($string, $length, $dot = ' ...') {
	$charset = 'utf-8';

	if(strlen($string) <= $length) {
		return $string;
	}

	$string = str_replace(array('&amp;', '&quot;', '&lt;', '&gt;'), array('&', '"', '<', '>'), $string);

	$strcut = '';
	if(strtolower($charset) == 'utf-8') {

		$n = $tn = $noc = 0;
		while($n < strlen($string)) {

			$t = ord($string[$n]);
			if($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
				$tn = 1; $n++; $noc++;
			} elseif(194 <= $t && $t <= 223) {
				$tn = 2; $n += 2; $noc += 2;
			} elseif(224 <= $t && $t < 239) {
				$tn = 3; $n += 3; $noc += 2;
			} elseif(240 <= $t && $t <= 247) {
				$tn = 4; $n += 4; $noc += 2;
			} elseif(248 <= $t && $t <= 251) {
				$tn = 5; $n += 5; $noc += 2;
			} elseif($t == 252 || $t == 253) {
				$tn = 6; $n += 6; $noc += 2;
			} else {
				$n++;
			}

			if($noc >= $length) {
				break;
			}

		}
		if($noc > $length) {
			$n -= $tn;
		}

		$strcut = substr($string, 0, $n);

	} else {
		for($i = 0; $i < $length; $i++) {
			$strcut .= ord($string[$i]) > 127 ? $string[$i].$string[++$i] : $string[$i];
		}
	}

	$strcut = str_replace(array('&', '"', '<', '>'), array('&amp;', '&quot;', '&lt;', '&gt;'), $strcut);

	return $strcut.$dot;
}